<?PHP

include_once("debugging.php");

class Table
{
	protected $mSourceFile;
	protected $mFieldNames;
	protected $mSearchable;
	protected $mRowData = array( );
	protected $mPath;
	protected $mDirty = false;

	function Table($path) {
		$this->mPath = $path;
		$lines = file($path, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
		$this->mSourceFile = $path;

		if(count($lines) < 1) return;

		$this->mFieldNames = explode('|', strToLower( $lines[0] ) );

		for($i = 0; $i < count($this->mFieldNames); $i++) {
			$name = $this->mFieldNames[$i];
	
			if(strlen($name) > 1 && $name{0} == '+') {
				// Remove the '+'
				$name = substr($name, 1);

				// Mark as searchable
				$this->mSearchable[$name] = true;

				// Update the name
				$this->mFieldNames[$i] = $name;
			}
			else {
				$this->mSearchable[$name] = false;
			}
		}

		for($i = 1; $i < count($lines); $i++) {
			$line = $lines[$i];
			$data = explode('|', $line);
			$uid = $data[0];
			$merged = array_combine($this->mFieldNames, $data);
			$this->mRowData[$uid] = $merged;
		}
	}

	function save() {
		if($this->mDirty === false) return FALSE;

		$tmp = "{$this->mPath}.new";
		if(($handle = fopen($tmp, "w")) === FALSE) {
			return FALSE;
		}
		
		$fields = $this->mFieldNames;
		for($i = 0; $i < count($fields); $i++) {
			if($this->mSearchable[$this->mFieldNames[$i]]) {
				$fields[$i] = "+{$fields[$i]}";
			}
		}
		$line = implode('|', $fields);
		fwrite($handle, "{$line}\n");

		foreach($this->mRowData as $row) {
			$line = implode('|', $row);
			fwrite($handle, "{$line}\n");
		}

		fclose($handle);

		rename($tmp, $this->mPath);
		return TRUE;
	}

	function hasField( $field ) {
		return ! ( array_search( $field, $this->mFieldNames ) === FALSE );
	}

	// Fetch ONE result by the ID
	function fetchId($id) {
		$key = $this->mFieldNames[0];
		$result = $this->simpleSearch($key, $id);

		if(count($result) == 0) return null;

		$keys = array_keys($result);
		$row = $result[ $keys[0] ];
		return $row;
	}

	function simpleSearch($where, $value) {
		$result = array( );
		$where = strToLower($where);

		foreach($this->mRowData as $row) {
			$uid = $row[ $this->mFieldNames[0] ];

			if(strcmp($value, $row[$where]) == 0) {
				$result[$uid] = $row;
			}
		}
		return $result;
	}

	function hashSearch($mappings) {
		if(count($mappings) == 0) {
			$result = $this->mRowData;
			return $result;
		}

		$keys = array_keys($mappings);
		$result = array ( );

		foreach($this->mRowData as $row) {
			$ok = true;
			foreach($keys as $key) {
				$value = $mappings[$key];
				if($row[$key] != $value) {
					$ok = false;
					break;
				}
			}
			if($ok === true) {
				$k = array_keys( $row );
				$result[ $row[ $k[0] ] ] = $row;
			}
		}

		return $result;
	}
	function hashTermSearch($mappings, $terms) {
		// Hash searching first should make this a little quicker.
		$result = $this->hashSearch($mappings);
		debug_print("Got mah result");

		if(count($terms) == 0) return $result;

		foreach($result as $row) {
			$match = false;
			$primaryKey = $this->mFieldNames[0];

			// Get the unique identifier for this row so we can delete it later if needed
			$uid = $row[ $primaryKey ];

			foreach($terms as $term) {
				// Trim it up in case it has been passed funny
				$term = trim($term);

				// If it is empty then we got ourselves a pickle
				if(empty($term)) continue;

				// Loop through the field names
				foreach($this->mFieldNames as $name) {
					if($this->mSearchable[$name]) {
						debug_print("$name is searchable...");
						debug_print("\tlooking for $term");
						$index = stristr($row[$name], $term);

						debug_print("\tstristr returned $index");
		
						if($index === false) {
							debug_print("{$row[$name]} doesn't contain $term");
						}
						else {
							debug_print("{$row[$name]} has $term");
							$match = true;
						}
					}
				}
			}	
			if($match == false) {
				debug_print("removing $uid");
				unset( $result[ $uid  ] );
			}
		}
		return $result;
	}

	function insert($values) {
		$prikey = $this->getPrimaryKey();

		$row = array();
		
		foreach($this->mFieldNames as $field) {
			if(isset($values[$field])) {
				$row[$field] = $values[$field];
			}
			else {
				$row[$field] = "";
			}
		}

		if(!isset($values[$prikey])) {
			$data = $this->mRowData;
			krsort($data);

			if(count($data) > 0) {
				// A hacky way of getting the first element.
				foreach($data as $tmp) {
					$last_id = $tmp[ $this->getPrimaryKey() ];
					break;
				}
			}
			else {
				// Force the new ID to be 0
				$last_id = -1;
			}

			$id = $last_id + 1;
			$row[$prikey] = $id;
		}

		$this->mDirty = true;
		$this->mRowData[] = $row;
	}

	function delete($where) {
		$result = $this->hashSearch($where);

		$prikey = $this->getPrimaryKey();

		foreach($result as $row) {
			$id = $row[ $prikey ];
			unset ($this->mRowData[ $id ]);
			$this->mDirty = true;
		}
	}

	function getPrimaryKey() {
		return $this->mFieldNames[0];		
	}
}

?>
